#include <iostream>
#include <time.h>
#include <list>
#include <vector>
#include <algorithm>
#include "Mylist.hpp"
using namespace std;

void Test1(){
  cout << "Test1: " << endl;
  int arr[] = {1, 2, 3, 4, 5};
  Mylist<int> lt(arr, arr+5);
  Mylist<int>::iterator it = lt.begin();
  while(it != lt.end())
  {
    if(*it % 2 == 0)
    {
      lt.insert(it,*it*10);
      lt.insert(it,*it*100);
    }
    ++it;
  }

  for(int e : lt)
  {
    cout << e << " ";
  }
  cout <<endl;
}

void Test2(){
  cout << "Test2: " << endl;
  int arr[] = {1, 2, 2, 3, 4, 4, 5, 4, 4, 4};
  Mylist<int> lt(arr, arr+10);
  Mylist<int>::iterator it = lt.begin();
  while(it != lt.end())
  {
    if(*it % 2 == 0)
    {
      it = lt.erase(it);
    }
    else{
      ++it;
    }
  }
  
  for(int e : lt)
  {
    cout << e << " ";
  }
  cout <<endl;
}

void Test3(){
  std::list<int> mylist1, mylist2;
  std::list<int>::iterator it;

  // set some initial values:
  for (int i=1; i<=4; ++i)
     mylist1.push_back(i);      // mylist1: 1 2 3 4

  for (int i=1; i<=3; ++i)
     mylist2.push_back(i*10);   // mylist2: 10 20 30

  it = mylist1.begin();
  ++it;                         // points to 2

  mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                // mylist2 (empty)
                                // "it" still points to 2 (the 5th element)
                                          
  mylist2.splice (mylist2.begin(),mylist1, it);
                                // mylist1: 1 10 20 30 3 4
                                // mylist2: 2
                                // "it" is now invalid.
  
  ++(*it);
  cout << *it << endl;

  std::cout << "mylist1 contains:";
  for (it=mylist1.begin(); it!=mylist1.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  std::cout << "mylist2 contains:";
  for (it=mylist2.begin(); it!=mylist2.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';
}

void Test4(){
  int myints[]= {17,89,7,14,89};
  std::list<int> mylist (myints,myints+5);

  mylist.remove(89);

  std::cout << "mylist contains:";
  for (std::list<int>::iterator it=mylist.begin(); it!=mylist.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n'; 
}

void Test5(){
  list<int> lt;
  vector<int> v1;
  srand(time(nullptr));
  size_t k = 1000000;
  for(size_t i = 0; i<k; ++i)
  {
    int e = rand();
    lt.push_back(e);
    v1.push_back(e);
  }
  
  //list_sort:
  double begin1 = clock();
  lt.sort();
  double end1 = clock();

  //vector_sort:
  double begin2 = clock();
  sort(v1.begin(), v1.end());
  double end2 = clock();

  //vector_copy_sort:
  vector<int> v2(k);
  double begin3 = clock();
  //for(auto e : lt)
  //{
  //  v2.push_back(e);
  //}
  copy(lt.begin(), lt.end(), v2.begin());
  sort(v2.begin(), v2.end());
  copy(v2.begin(), v2.end(), lt.begin());
  //size_t i = 0;
  //for(auto &e :lt)
  //{
  //  e = v1[i++];
  //}
  double end3 = clock();

  cout << "list_sort: " << (end1-begin1)/CLOCKS_PER_SEC*1000 << endl;
  cout << "vector_sort: " << (end2-begin2)/CLOCKS_PER_SEC*1000 <<endl;
  cout << "vector_copy_sort: " << (end3-begin3)/CLOCKS_PER_SEC*1000 <<endl;
}

void Test6(){
  Mylist<int> mlt;
  mlt.push_back(1);
  mlt.push_back(2);
  mlt.push_back(3);
  mlt.push_back(4);
  mlt.push_back(5);

  for(auto it = mlt.begin(); it!=mlt.end(); ++it)
  {
    cout << *it << " ";
  }
  cout << endl;

  for(int &e : mlt)
  {
    e *= 2;
  }

  for(int e : mlt)
  {
    cout << e << " ";
  }
  cout << endl;
}

struct Pos{
  int _row;
  int _col;
  Pos(int row = 0, int col = 0)
    :_row(row),
    _col(col)
  {}
};

void Test7(){
  cout << "Test7: " << endl;
  Mylist<Pos> mlt;
  mlt.push_back(Pos(10,10));
  mlt.push_back(Pos(20,20));

  for(auto it = mlt.begin(); it != mlt.end(); ++it)
  {
    cout << it->_row << ":" << it->_col << endl;
  }
}

void print_list(const Mylist<int> &list){
  Mylist<int>::const_iterator it = list.begin();
  while(it != list.end())
  {
    //*it = 0;
    cout << *it << " ";
    ++it;
  }
  cout << endl;
}

void Test8(){
  cout << "Test8: " << endl;
  Mylist<int> mlt;
  mlt.push_back(1);
  mlt.push_back(2);
  mlt.push_back(3);
  mlt.push_back(4);
  mlt.push_back(5);
  print_list(mlt); 
}

void Test9(){
  cout << "Test9: " << endl;
  Mylist<int> mlt;
  mlt.push_back(1);
  mlt.push_back(2);
  mlt.push_back(3);
  mlt.push_back(4);
  mlt.push_back(5);
  print_list(mlt);

  mlt.push_front(1);
  mlt.push_front(2);
  mlt.push_front(3);
  mlt.push_front(4);
  mlt.push_front(5);
  print_list(mlt);

  mlt.pop_back();
  mlt.pop_back();
  print_list(mlt);

  mlt.pop_front();
  mlt.pop_front();
  print_list(mlt);

  //mlt.erase(mlt.end());
}

void Test10(){
  int arr[] = {1,2,3,4,5,6,7,8,9,10};
  Mylist<int> mlt(arr, arr+10);
  print_list(mlt);
  Mylist<int> copy(mlt);
  print_list(copy);
  Mylist<int> assign;
  assign = mlt;
  print_list(assign);
}

int main(){
  //Test10();
  Mylist<int> mlt;
  mlt.pop_back();
  return 0;
}
